package cn.aezo.minions.gen;

import cn.aezo.minions.common.Result;
import cn.aezo.minions.gen.handler.GenCodeHandler;
import cn.aezo.minions.gen.mapper.ProjectConfigDao;
import cn.aezo.minions.gen.mapper.TemplateDao;
import cn.aezo.minions.gen.model.ProjectConfig;
import cn.aezo.minions.gen.model.Template;
import cn.aezo.minions.gen.model.TemplateItem;
import cn.aezo.minions.web.services.TemplateService;
import cn.aezo.utils.base.MiscU;
import cn.aezo.utils.base.ValidU;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by smalle on 2017/11/3.
 */
@Slf4j
@Service
public class GenService {
    @Autowired
    private ProjectConfigDao projectConfigDao;

    @Autowired
    TemplateService templateService;

    @Autowired
    TemplateDao templateDao;

    @Autowired
    Plugins plugins;

    /**
     * 生成项目
     * @param projectConfigId
     * @return
     */
    public Result genProject(Long projectConfigId) {
        // 初始化Context
        Result initRes = initContext(projectConfigId);
        if(Result.isError(initRes)) return initRes;
        Map<String, Object> data = (Map<String, Object>) initRes.getData();

        Context context = (Context) data.get("context");
        List<GenCodeHandler> handlers = (List<GenCodeHandler>) data.get("handlers");

        // 初始化Handler
        for (GenCodeHandler handler : handlers) {
            handler.init(context);
        }

        // 执行Handler
        for (GenCodeHandler handler : handlers) {
            String moduleName = context.getCurrentModule();

            handler.handleGenCode(context);

            // 某个handler内部可修改模块名，此处进行还原
            context.setCurrentModule(moduleName);
        }

        return Result.success();
    }

    private Result initContext(Long projectConfigId) {
        // 可传递一个params动态参数 TODO
        // 查询项目配置信息
        ProjectConfig projectConfig = projectConfigDao.findOne(projectConfigId);
        if(ValidU.isEmpty(projectConfig))
            return Result.failure("无效的项目配置");

        // 获取模板
        Long templateId = 1157235318189994468L; // TODO
        Template template = templateDao.selectById(templateId);

        // 获取模板树(Map)
        Result result = templateService.getTemplateWithLevel(templateId);
        if(Result.isError(result)) return result;

        // 重新组装模板树实体
        List<TemplateItem> templateItems = new ArrayList<>();
        List<Map<String, Object>> list = (List<Map<String, Object>>) result.getData();
        if(ValidU.isNotEmpty(list)) {
            for (Map<String, Object> item : list) {
                ObjectMapper objectMapper = new ObjectMapper();
                objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                templateItems.add(objectMapper.convertValue(item, TemplateItem.class));
            }
        }
        template.setTemplateItems(templateItems);

        Context context = Context.init(projectConfig, template);
        List<GenCodeHandler> handlers = plugins.getGenCodeHandler();
        return Result.success(MiscU.Instance.toMap("context", context,"handlers", handlers));
    }

    public static void main(String[] args) {
        String path = "D:\\temp\\test.bat";
        Runtime run = Runtime.getRuntime();
        try {
            // run.exec("cmd /k ipconfig"); // Runtime.getRuntime().exec("cmd /k calc"); // 打开计算机，命令calc, && 可连接多条命令
            // run.exec(new String[]{"cd C:\\Users\\smalle\\Desktop\\vue-admin\\vueAdmin-template", "npm run dev"});

            Process process = run.exec("cmd.exe /k start " + path);
            // InputStream in = process.getInputStream();
            // while (in.read() != -1) {
            //     System.out.println(in.read());
            // }
            // in.close();
            // process.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
